package main

import (
	"fmt"
	"ndemo/mynl"
)

/**
 * 第1节
 * 本节的目的是迅速的实现一个最精简的语言的功能，让你了解一门计算机语言的骨架。
 *
 * 知识点：
 * 1.递归下降的方法做词法分析；
 * 2.语义分析中的引用消解（找到函数的定义）；
 * 3.通过遍历AST的方法，执行程序。
 *
 * 本节采用的语法规则是极其精简的，只能定义函数和调用函数。定义函数的时候，还不能有参数。
 *
 * EBNF规则：
 * prog = (functionDecl | functionCall)*
 * functionDecl: "function" Identifier "(" ")"  functionBody
 * functionBody : "{" functionCall* "}"
 * functionCall : Identifier "(" parameterList? ")"
 * parameterList : StringLiteral ("," StringLiteral)*
 *
 * 其他：
 * 系统调用以nl.开始
 * functionCall.name.startsWith("nl.")
 *
 * 例子中的两个Token数组，需要手工切换后tsc编译，再运行
 * 运行：
 * export GO111MODULE=auto
 * go env -w GOPROXY=https://goproxy.cn,direct
 * go build
 *
 */

// 第1个Token数组，代表了下面这段程序做完词法分析后的结果：
/*
function sayHello(){
    nl.println("Hello World!");
}
sayHello();
*/
var tokenArraySayHello = []mynl.Token{
	{Kind: mynl.TokenKind_Keyword, Text: "function"},
	{Kind: mynl.TokenKind_Identifier, Text: "sayHello"},
	{Kind: mynl.TokenKind_Seperator, Text: "("},
	{Kind: mynl.TokenKind_Seperator, Text: ")"},
	{Kind: mynl.TokenKind_Seperator, Text: "{"},
	{Kind: mynl.TokenKind_Identifier, Text: "nl.println"},
	{Kind: mynl.TokenKind_Seperator, Text: "("},
	{Kind: mynl.TokenKind_StringLiteral, Text: "Hello World!"},
	{Kind: mynl.TokenKind_Seperator, Text: ")"},
	{Kind: mynl.TokenKind_Seperator, Text: ";"},
	{Kind: mynl.TokenKind_Seperator, Text: "}"},
	{Kind: mynl.TokenKind_Identifier, Text: "sayHello"},
	{Kind: mynl.TokenKind_Seperator, Text: "("},
	{Kind: mynl.TokenKind_Seperator, Text: ")"},
	{Kind: mynl.TokenKind_Seperator, Text: ";"},
	{Kind: mynl.TokenKind_EOF, Text: ""},
}

// 第2个Token数组，代表了下面这段程序做完词法分析后的结果：
/*
function foo(){
    nl.println("in foo...")
}
function bar(){
    nl.println("in bar...")
    foo()
}
bar()
*/
var tokenArrayFooBar = []mynl.Token{
	{Kind: mynl.TokenKind_Keyword, Text: "function"},
	{Kind: mynl.TokenKind_Identifier, Text: "foo"},
	{Kind: mynl.TokenKind_Seperator, Text: "("},
	{Kind: mynl.TokenKind_Seperator, Text: ")"},
	{Kind: mynl.TokenKind_Seperator, Text: "{"},
	{Kind: mynl.TokenKind_Identifier, Text: "nl.println"},
	{Kind: mynl.TokenKind_Seperator, Text: "("},
	{Kind: mynl.TokenKind_StringLiteral, Text: "in foo..."},
	{Kind: mynl.TokenKind_Seperator, Text: ")"},
	{Kind: mynl.TokenKind_Seperator, Text: ";"},
	{Kind: mynl.TokenKind_Seperator, Text: "}"},
	{Kind: mynl.TokenKind_Keyword, Text: "function"},
	{Kind: mynl.TokenKind_Identifier, Text: "bar"},
	{Kind: mynl.TokenKind_Seperator, Text: "("},
	{Kind: mynl.TokenKind_Seperator, Text: ")"},
	{Kind: mynl.TokenKind_Seperator, Text: "{"},
	{Kind: mynl.TokenKind_Identifier, Text: "nl.println"},
	{Kind: mynl.TokenKind_Seperator, Text: "("},
	{Kind: mynl.TokenKind_StringLiteral, Text: "in bar..."},
	{Kind: mynl.TokenKind_Seperator, Text: ")"},
	{Kind: mynl.TokenKind_Seperator, Text: ";"},
	{Kind: mynl.TokenKind_Identifier, Text: "foo"},
	{Kind: mynl.TokenKind_Seperator, Text: "("},
	{Kind: mynl.TokenKind_Seperator, Text: ")"},
	{Kind: mynl.TokenKind_Seperator, Text: ";"},
	{Kind: mynl.TokenKind_Seperator, Text: "}"},
	{Kind: mynl.TokenKind_Identifier, Text: "bar"},
	{Kind: mynl.TokenKind_Seperator, Text: "("},
	{Kind: mynl.TokenKind_Seperator, Text: ")"},
	{Kind: mynl.TokenKind_Seperator, Text: ";"},
	{Kind: mynl.TokenKind_EOF, Text: ""},
}

/////////////////////////////////////////////////////////////////////////
// 主程序

func compileAndRun() {
	//词法分析
	//var tokenizer = mynl.NewTokenizer(tokenArraySayHello)
	var tokenizer = mynl.NewTokenizer(tokenArrayFooBar)
	fmt.Println("\n程序所使用的Token:")
	for _, x := range tokenArrayFooBar {
		fmt.Println(x)
	}

	//语法分析
	var prog = mynl.NewParser(*tokenizer).ParseProg()
	fmt.Println("\n语法分析后的AST，注意自定义函数的调用未被消解:")
	prog.Dump("")

	//语义分析
	mynl.NewRefResolver().VisitProg(prog)
	fmt.Println("\n语义分析后的AST，注意自定义函数的调用已被消解:")
	prog.Dump("")

	//运行程序
	fmt.Println("\n运行当前的程序:")
	var retVal = mynl.NewIntepretor().VisitProg(prog)
	fmt.Printf("程序返回值：%d\n", retVal)
}

func main() {
	//运行示例
	compileAndRun()
}
